package gormredis

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/garyburd/redigo/redis"
	redigo "github.com/garyburd/redigo/redis"
	"strings"
	"sync"
)

// idnex
// 创建时间:下午3:27
// 创建人:lixu

var (
	GLOBALLREDISPOOL   *redis.Pool
	GLOBALLREDISCONFIG MRedisConfig
	// 互斥锁
	settingMutex sync.Mutex
)

type MRedisConfig struct {
	Host   string `json:"host"`
	Port   string `json:"port"`
	Pwd    string `json:"pwd"`
	Db     string `json:"Db"`
	Prefix string `json:"prefix"`
}

func setFormatValue(result interface{}) (content string) {
	bys, _ := json.Marshal(result)
	content = string(bys)
	return
}

func formatValue(content string, result interface{}) (err error) {
	err = json.Unmarshal([]byte(content), &result)
	return
}

func formatKeyName(kname string) (name string) {
	name = GLOBALLREDISCONFIG.Prefix + kname
	return

}

func NewRedis(config MRedisConfig) (errs []error) {
	GLOBALLREDISCONFIG = config

	settingMutex.Lock()
	defer settingMutex.Unlock()

	pool_size := 50

	GLOBALLREDISPOOL = redigo.NewPool(func() (redigo.Conn, error) {
		c, err := redigo.Dial("tcp", fmt.Sprintf("%s:%s", config.Host, config.Port))
		if err != nil {
			errs = append(errs, err)
			return nil, err
		}
		if _, err := c.Do("AUTH", config.Pwd); err != nil {
			c.Close()
			errs = append(errs, err)
			return nil, err
		}
		if _, err := c.Do("SELECT", config.Db); err != nil {
			c.Close()
			errs = append(errs, err)
			return nil, err
		}

		return c, nil
	}, pool_size)

	return

}

func GetRedisCoon() (conn redigo.Conn, err error) {
	if GLOBALLREDISPOOL == nil {
		err = errors.New("GLOBALLREDISPOOL nil")
		return
	}
	conn = GLOBALLREDISPOOL.Get()
	return
}

func Set(name string, content interface{}, times int) (err error) {

	redis, err := GetRedisCoon()
	if err != nil {
		err = fmt.Errorf("Set GetRedisCoon::%s", err.Error())
		return
	}
	defer redis.Close()

	if times > 0 {
		_, err = redis.Do("set", formatKeyName(name), setFormatValue(content), "EX", times)
	} else {
		_, err = redis.Do("set", formatKeyName(name), setFormatValue(content))
	}

	return
}

func Get(name string, result interface{}) (exist bool, err error) {

	redis, err := GetRedisCoon()
	if err != nil {
		err = fmt.Errorf("Set GetRedisCoon::%s", err.Error())
		return
	}

	defer redis.Close()

	content, err := redigo.String(redis.Do("GET", formatKeyName(name)))
	if err != nil {
		if strings.Contains(err.Error(), "nil returned") {
			err = nil
			return
		}
		err = fmt.Errorf("Get String::%s", err.Error())
		return
	}

	exist = true
	err = formatValue(content, &result)
	if err != nil {
		err = fmt.Errorf("Get formatValue::%s", err.Error())
		return
	}

	return
}
